package jdepend.plugin;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.logging.Logger;
import javax.swing.Action;
import javax.swing.SwingUtilities;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import jdepend.xmlui.JDepend;
import org.netbeans.api.extexecution.ExecutionDescriptor;
import org.netbeans.api.extexecution.ExecutionService;
import org.netbeans.api.project.Project;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.StatusDisplayer;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.Node;
import org.openide.util.ContextAwareAction;
import org.openide.util.Exceptions;
public final class jDependAnalysis implements ActionListener {
private final Project context;
private FileObject jdependFolder = null;
private jDependProcessThread thread;
private Process process;
public jDependAnalysis(Project context) {
this.context = context;
}
@Override
public void actionPerformed(ActionEvent ev) {
new jDependThread().start();
}
private void openFileInIDE(FileObject file) {
try {
DataObject newDo = DataObject.find(file);
final Node node = newDo.getNodeDelegate();
Action a = node.getPreferredAction();
if (a instanceof ContextAwareAction) {
a = ((ContextAwareAction) a).createContextAwareInstance(node.getLookup());
}
if (a != null) {
a.actionPerformed(new ActionEvent(node, ActionEvent.ACTION_PERFORMED, "")); // NOI18N
}
} catch (DataObjectNotFoundException ex) {
Exceptions.printStackTrace(ex);
}
}
class jDependThread extends Thread {
@Override
public void run() {
try {
StatusDisplayer.getDefault().setStatusText(context.getProjectDirectory().getPath());
if (context.getProjectDirectory().getFileObject("jdepend") != null) {
jdependFolder = context.getProjectDirectory().getFileObject("jdepend");
jdependFolder.delete();
}
jdependFolder = context.getProjectDirectory().createFolder("jdepend");
FileObject manifestFile = context.getProjectDirectory().getFileObject("manifest.mf");
if (manifestFile == null) {
StatusDisplayer.getDefault().setStatusText("No manifest file?");
} else {
if (context.getProjectDirectory().getFileObject("build") == null) {
DialogDisplayer.getDefault().notifyLater(
new NotifyDescriptor.Message(
"JDepend needs a compiled project. Please compile "
+ "your project and retry afterwards.",
NotifyDescriptor.INFORMATION_MESSAGE));
return;
}
FileObject report = jdependFolder.createData("report", "xml");
JDepend.main(new String[]{"-file", report.getPath(),
context.getProjectDirectory().getFileObject("build").getPath()});
StatusDisplayer.getDefault().setStatusText("See report at: " + report.getPath());
transform(new File(report.getPath()));
//Now convert to image
execute();
}
} catch (Exception ex) {
DialogDisplayer.getDefault().notifyLater(
new NotifyDescriptor.Message(
"Something wrong happened while creating the report. "
+ "Please try again. \nIf it keeps happening please create "
+ "a bug with as much information as you can: "
+ "http://kenai.com/jira/browse/JDEPEND_PLUGIN\n" + ex,
NotifyDescriptor.ERROR_MESSAGE));
Exceptions.printStackTrace(ex);
}
}
}
private void transform(File report) {
try {
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer =
tFactory.newTransformer(new javax.xml.transform.stream.StreamSource(jDependAnalysis.class.getResourceAsStream("jdepend2dot.xsl")));
transformer.transform(new javax.xml.transform.stream.StreamSource(report.getPath()),
new javax.xml.transform.stream.StreamResult(new FileOutputStream(jdependFolder.getPath()
+ System.getProperty("file.separator") + "report.dot")));
} catch (Exception e) {
Exceptions.printStackTrace(e);
}
}
public Integer execute() throws ExecutionException, InterruptedException {
final Callable<Process> atlassianProcess = new Callable<Process>() {
@Override
public Process call() throws IOException {
FileObject image = jdependFolder.createData("report", "png");
ArrayList<String> commands = new ArrayList<String>();
commands.add("dot");
commands.add("-Tpng");
commands.add("-o");
commands.add(image.getPath());
commands.add(jdependFolder.getPath()
+ System.getProperty("file.separator") + "report.dot");
for (int i = 0; i < commands.size(); i++) {
Logger.getLogger(jDependAnalysis.class.getSimpleName()).fine(
commands.get(i));
}
ProcessBuilder pb = new ProcessBuilder(commands);
pb.redirectErrorStream(true);
process = pb.start();
try {
process.waitFor();
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
}
return process;
}
};
thread = new jDependProcessThread(atlassianProcess);
try {
SwingUtilities.invokeAndWait(thread);
} catch (InvocationTargetException ex) {
Exceptions.printStackTrace(ex);
}
return thread.getTaskResult();
}
private class jDependProcessThread extends Thread {
private final Callable<Process> jDependProcess;
public jDependProcessThread(Callable<Process> atlassianProcess) {
this.jDependProcess = atlassianProcess;
}
int taskResult = 0;
@Override
public void run() {
try {
ExecutionDescriptor descriptor = new ExecutionDescriptor().frontWindow(true).controllable(true);
ExecutionService service = ExecutionService.newService(jDependProcess,
descriptor, "jDepend Report Creator");
Future<Integer> task = service.run();
taskResult = task.get();
openFileInIDE(jdependFolder.getFileObject("report", "png"));
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (ExecutionException ex) {
Exceptions.printStackTrace(ex);
}
}
public int getTaskResult() {
return taskResult;
}
}
}